!function () {
    // 保存原生方法
    const MyGetOwnPropertySymbols = Object.getOwnPropertySymbols;

    Object.getOwnPropertySymbols = function getOwnPropertySymbols() {
        const result = MyGetOwnPropertySymbols.apply(this, arguments);
        for (let i = 0; i < result.length; i++) {
            if (result[i].toString().indexOf("myToString") !== -1) return [];
        }
        return result;
    };

    const $toString = Function.prototype.toString;
    const myFunction_toString_symbol = Symbol('myToString(' + (Math.random()).toString(36) + ')');

    const myToString = function () {
        return typeof this === 'function' && this[myFunction_toString_symbol] || $toString.call(this);
    };

    function set_native(func, key, value) {
        Object.defineProperty(func, key, {
            enumerable: false,
            configurable: true,
            writable: true,
            value: value
        });
    }

    // 删除原生 toString
    delete Function.prototype.toString;

    // 重定义 toString
    set_native(Function.prototype, "toString", myToString);
    set_native(Function.prototype.toString, myFunction_toString_symbol, "function toString() { [native code] }");
    set_native(Object.getOwnPropertySymbols, myFunction_toString_symbol, `function getOwnPropertySymbols() { [native code] }`);

    // 插件对象
    const plugin = {
        func_set_native: (func) => {
            set_native(func, myFunction_toString_symbol, `function ${func.name || ''}() { [native code] }`);
        },
        func_set_native_Div: (func, name) => {
            set_native(func, myFunction_toString_symbol, `function ${name || ''}() { [native code] }`);
        },
        defineProperty: function defineProperty(obj, key, value, configurable, enumerable, writable, getter, setter) {
            const attr = {
                configurable,
                enumerable
            };
            if (value !== undefined) {
                attr.value = value;
            }
            if (writable !== undefined) {
                attr.writable = writable;
            }
            if (getter) {
                attr.get = getter;
            }
            if (setter) {
                attr.set = setter;
            }
            Object.defineProperty(obj, key, attr);
        },
        rename: function rename(obj, objname) {
            Object.defineProperties(obj, {
                [Symbol.toStringTag]: {
                    value: objname,
                    configurable: true,
                    writable: false,
                    enumerable: false
                }
            });
        },
        throwError: function (err, message, stack) {
            if (err === undefined) return;
            let e = new err();
            e.message = message;
            if (stack === undefined) {
                e.stack = `${err.name}: ${message}
    at snippet:///Script%20snippet%20%231:2:5`;
            }
            throw e;
        }
    };

    function main(OBJECT, proto) {
        let tempProto = OBJECT;
        while (true) {
            tempProto = tempProto.__proto__;
            if (tempProto === null) {
                console.error("在实例原型链中未找到指定原型模板");
                break;
            }
            if (tempProto.constructor === proto) {
                console.log(getProto(OBJECT, proto));
                console.info("在实例原型链中找到指定原型模板");
                break;
            }
        }
    }

    function getProto(OBJECT, proto) {
        let JsCode =
            `
        ${proto.name} = function ${proto.name}(){
            debugger;
        };
        \r\n`;

        let names = Object.getOwnPropertyNames(proto.prototype);
        for (let i = 0; i < names.length; i++) {
            const msf = Object.getOwnPropertyDescriptor(proto.prototype, names[i]);
            console.log(msf);
            const value = typeof msf['value'] == 'function' ?
                `function ${msf['value'].name}(){ debugger; }` :
                msf['value'] === undefined ? `undefined` : `(function (){ debugger; })()`;
            const set = msf['set'] === undefined ? `undefined` : `function set(){ debugger; }`;
            const get = msf['get'] === undefined ? `undefined` : `function get(){ debugger; }`;

            JsCode += `
            Object.defineProperty(${proto.name}.prototype, "${names[i]}", {
                configurable: ${msf['configurable']},
                enumerable: ${msf['enumerable']},
                ${msf['writable'] === undefined ? "" : `writable: ${msf['writable']},`}
                ${msf['value'] === undefined ? "" : `value: ${value},`}
                ${msf['set'] === undefined ? "" : `set: ${set},`}
                ${msf['get'] === undefined ? "" : `get: ${get},`}
            });
            \r\n`;

            if (msf['get'] != undefined) {
                JsCode += `
                Object.defineProperty(Object.getOwnPropertyDescriptor(${proto.name}.prototype, "${names[i]}").get, "name", {
                    value: "get " + "${names[i]}",
                    configurable: true,
                    enumerable: true,
                    writable: true
                });`;
            }
            if (msf['set'] != undefined) {
                JsCode += `
                Object.defineProperty(Object.getOwnPropertyDescriptor(${proto.name}.prototype, "${names[i]}").set, "name", {
                    value: "set " + "${names[i]}",
                    configurable: true,
                    enumerable: true,
                    writable: true
                });`;
            }
        }
        return JsCode;
    }

    // 示例：创建一个名为 MyCustom 的类
    // function MyCustom() {}
    // plugin.rename(MyCustom, 'MyCustom');  // 为 MyCustom 添加 toStringTag
    // const customInstance = new MyCustom();

    // 检查实例的原型链
    // main(customInstance, MyCustom);

}.bind(this)();